<template>
  <el-button
    :ref="changeRef"
    round
    type="primary"
    :loading="loading"
    v-bind="getBindValue"
    @click="handleCilck"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
  >
    <!-- 优先显示传入的内容 -->
    <template v-if="$slots.default">
      <slot></slot>
    </template>

    <template v-else>
      <!-- 默认内容 -->
      <z-icon v-if="preIcon" :icon="preIcon" />
      <span>{{ title ? title : '' }}</span>
      <z-icon v-if="postIcon" :icon="postIcon" />
    </template>

    <!-- 具名插槽 -->
    <template v-for="(_, name) in getRenderSlots" :key="name" #[name]="slotProps">
      <slot :name="name" v-bind="slotProps"></slot>
    </template>
  </el-button>
</template>

<script lang="ts" setup>
import type { ZButtonInstance, ZButtonProps } from '../types'

defineOptions({ name: 'ZButton', inheritAttrs: false })

const props = withDefaults(defineProps<ZButtonProps>(), {
  preIcon: '',
  postIcon: '',
  title: '',
  animation: true,
  animationTime: 0.2
})

const vm = getCurrentInstance()
const attrs = useAttrs()
const loading = ref<boolean>(false) // 按钮加载状态
const buttonElement = ref<Record<string, any> | null>(null)
const getBindValue = computed(() => {
  const delArr: string[] = [
    'title',
    'preIcon',
    'postIcon',
    'animation',
    'animationTime',
    'onClick',
    'loading'
  ]
  const obj = { ...attrs }
  Object.assign(obj, props)
  for (const key in obj) {
    if (delArr.indexOf(key) !== -1) {
      delete obj[key]
    }
  }
  return obj
})

const getRenderSlots = computed(() => {
  const delArr: string[] = ['default']
  const slots = { ...useSlots() }
  for (const key in slots) {
    if (delArr.indexOf(key) !== -1) {
      delete slots[key]
    }
  }
  return slots
})

// 鼠标悬停动画
const handleMouseEnter = () => {
  if (buttonElement.value && props.animation) {
    gsap.to(buttonElement.value, {
      y: -3,
      duration: props.animationTime,
      ease: 'power2.out'
    })
  }
}

// 鼠标离开动画
const handleMouseLeave = () => {
  if (buttonElement.value && props.animation) {
    gsap.to(buttonElement.value, {
      y: 0,
      duration: props.animationTime,
      ease: 'power2.out'
    })
  }
}

// 拦截点击事件
const handleCilck = async () => {
  loading.value = true
  try {
    await (attrs.onClick as any)?.()
    attrs
  } finally {
    loading.value = false
  }
}

const changeRef = (ButtonInstance: Record<string, any> | null) => {
  buttonElement.value = ButtonInstance?.ref || ButtonInstance
  if (vm) {
    vm.exposeProxy = vm.exposed = Object.assign(
      ButtonInstance || {},
      {} // 这里写暴露的方法
    ) as ZButtonInstance
  }
}

defineExpose((vm?.exposeProxy || {}) as ZButtonInstance)
</script>

<style lang="scss" scoped>
.el-button {
  transition: v-bind(animationTime) s;
}

:deep(.el-button.is-text) {
  padding: 8px 4px;
  margin-left: 0;
}

:deep(.el-button.is-link) {
  padding: 8px 4px;
  margin-left: 0;
}
</style>
